package org.opensource.extfaces.tags;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Stack;

import javax.el.ELException;
import javax.faces.FacesException;
import javax.faces.component.UIComponent;

import com.sun.facelets.FaceletContext;
import com.sun.facelets.FaceletException;
import com.sun.facelets.tag.TagAttribute;
import com.sun.facelets.tag.TagConfig;
import com.sun.facelets.tag.TagHandler;

public class ComponentTag extends TagHandler {
	private static final String xhtml = "/WEB-INF/facelets/tags/component/component.xhtml";
	private Map<String, Object> map = null;


	public ComponentTag(TagConfig config) {
		super(config);
		
	}

	public void apply(FaceletContext ctx, UIComponent parent)
			throws IOException, FacesException, FaceletException, ELException {
		map = new HashMap<String, Object>();
		Stack tagStack=Component.getStack();
		TagAttribute[] attributes = this.tag.getAttributes().getAll();
		Map config=Component.getComponentConfig(tagStack);
		for (int i = 0; i < attributes.length; i++) {
			TagAttribute attribute = attributes[i];
			String name = attribute.getLocalName();
			Object value = attribute.getValue(ctx);
			map.put(name, value);
			
		}
		if (!tagStack.isEmpty()) {		
			List items=getItems(config);
			addToItemList(items, tagStack.size());
		}
		else{
			config.putAll(map);
			ctx.setAttribute("containerXtype",config.get("xtype"));
		}
		tagStack.push(this.tagId);
		

		this.nextHandler.apply(ctx, parent);

		tagStack.pop();
		if(tagStack.isEmpty()){
			ctx.includeFacelet(parent, ctx.getFacesContext().getExternalContext()
					.getResource(xhtml));
			
		}
		ctx.setAttribute("config", config);
	}

	private List getItems(Map map) {
		List list = new ArrayList();
		if (map.get("items") != null) {
			list = (List) map.get("items");
		}
		map.put("items", list);
		return list;
	}



	private void addToItemList(List itemList, int depth) {
		if (depth-1 > 0) {
			Map map = (Map) itemList.get(itemList.size() - 1);
			List subList = (List) map.get("items");
			if (subList == null) {
				subList = new ArrayList();
				map.put("items", subList);
			}
			depth--;
			addToItemList(subList, depth);
		}
		else{
			itemList.add(map);
		}
	}
}
